package com.github.dengmin.mysql.shiro.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.github.dengmin.mysql.utils.HttpServletRequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Date;
import java.util.UUID;

/**
 * @Author dengmin
 * @Created 2020/8/14 下午1:31
 */
@Component
public class JwtUtil {
    private static final long serialVersionUID = 1L;
    private static JwtProperties jwtProperties;
    public JwtUtil(JwtProperties jwtProperties){
        JwtUtil.jwtProperties = jwtProperties;
    }

    /**
     * 生成token
     * @param username
     * @param salt
     * @param expireDuration
     * @return
     */
    public static String generateToken(String username, String salt, Duration expireDuration){
        if(StringUtils.isBlank(username)) return null;
        if(StringUtils.isBlank(salt)){
            salt = jwtProperties.getSecret();
        }
        Long expireSecond;
        if(expireDuration == null){
            expireSecond = jwtProperties.getExpireSecond();
        }else{
            expireSecond = expireDuration.getSeconds();
        }
        Date expireDate = DateUtils.addSeconds(new Date(), expireSecond.intValue());
        Algorithm algorithm = Algorithm.HMAC256(salt);
        return JWT.create()
                .withClaim("username", username)
                .withJWTId(UUID.randomUUID().toString().replaceAll("-", ""))
                .withIssuer(jwtProperties.getIssuer())
                .withSubject(jwtProperties.getSubject())
                .withAudience(jwtProperties.getAudience())
                .withIssuedAt(new Date())
                .withExpiresAt(expireDate).sign(algorithm);
    }

    public static boolean verifyToken(String token, String salt){
        try {
            Algorithm algorithm = Algorithm.HMAC256(salt);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(jwtProperties.getIssuer())
                    .withSubject(jwtProperties.getSubject())
                    .withAudience(jwtProperties.getAudience()).build();
            DecodedJWT jwt = verifier.verify(token);
            if (jwt != null) {
                return true;
            }
        }catch (Exception e){

        }
        return false;
    }

    public static DecodedJWT getJwtInfo(String token){
        return JWT.decode(token);
    }

    public static String getUsername(String token){
        if(StringUtils.isBlank(token)) return null;
        DecodedJWT decodedJWT = getJwtInfo(token);
        if(decodedJWT == null) return null;
        return decodedJWT.getClaim("username").asString();
    }

    public static Date getIssueAt(String token){
        DecodedJWT decodedJWT = getJwtInfo(token);
        if(decodedJWT == null) return null;
        return decodedJWT.getIssuedAt();
    }

    public static Date getExpireDate(String token){
        DecodedJWT decodedJWT = getJwtInfo(token);
        if(decodedJWT == null) return null;
        return decodedJWT.getExpiresAt();
    }

    /**
     * 判断token是否过期
     * @param token
     * @return
     */
    public static boolean isExpired(String token){
        Date expireDate = getExpireDate(token);
        if(expireDate == null) return true;
        return expireDate.before(new Date());
    }


    public static String getToken(){
        return getToken(HttpServletRequestUtil.getRequest());
    }

    public static String getToken(HttpServletRequest request){
        if(request == null){
            throw new IllegalArgumentException("request不能为空");
        }
        String token = request.getHeader("token");
        if(StringUtils.isBlank(token)){
            token = request.getParameter("token");
        }
        return token;
    }


}
